package com.liang.interview.server.service;

import cn.hutool.core.collection.CollUtil;
import com.liang.interview.api.enums.EngineEnum;
import com.liang.interview.api.req.InterviewSubmitReq;
import com.liang.interview.api.req.StartReq;
import com.liang.interview.api.vo.InterviewQuestionVO;
import com.liang.interview.api.vo.InterviewResultVO;
import com.liang.interview.api.vo.InterviewVO;
import com.liang.interview.server.entity.po.SubjectCategory;
import com.liang.interview.server.entity.po.SubjectInfo;
import com.liang.interview.server.entity.po.SubjectLabel;
import com.liang.interview.server.mapper.SubjectMapper;
import com.liang.interview.server.util.EvaluateUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class DefaultInterviewEngine implements InterviewEngine {

    private final SubjectMapper subjectMapper;

    private List<SubjectLabel> labels;
    private Map<Long, SubjectCategory> categoryMap;

    @PostConstruct
    public void init() {
        labels = subjectMapper.listAllLabel();
        categoryMap = subjectMapper.listAllCategory()
                .stream()
                .collect(
                        Collectors.toMap(SubjectCategory::getId, Function.identity())
                );
    }

    @Override
    public EngineEnum engineType() {
        return EngineEnum.DEFAULT;
    }

    @Override
    public InterviewVO analyse(List<String> KeyWords) {
        if (CollUtil.isEmpty(KeyWords)) {
            return new InterviewVO();
        }
        List<InterviewVO.Interview> views = labels.stream().filter(item -> KeyWords.contains(item.getLabelName())).map(item -> {
            InterviewVO.Interview interview = new InterviewVO.Interview();
            SubjectCategory subjectCategory = categoryMap.get(item.getCategoryId());
            if (Objects.nonNull(subjectCategory)) {
                interview.setKeyWord(String.format("%s-%s", subjectCategory.getCategoryName(), item.getLabelName()));
            } else {
                interview.setKeyWord(item.getLabelName());
            }
            interview.setCategoryId(item.getCategoryId());
            interview.setLabelId(item.getId());
            return interview;
        }).collect(Collectors.toList());

        InterviewVO vo = new InterviewVO();
        vo.setQuestionList(views);
        return vo;
    }

    @Override
    public InterviewQuestionVO start(StartReq req) {
        List<Long> ids = req.getQuestionList().stream()
                .map(StartReq.Key::getLabelId)
                .distinct()
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(ids)) {
             return new InterviewQuestionVO();
        }
        List<SubjectInfo> subjectInfos = subjectMapper.listSubjectByLabelIds(ids);
        List<InterviewQuestionVO.Interview> interviewList = subjectInfos.stream()
                .map(item -> {
                    InterviewQuestionVO.Interview interview = new InterviewQuestionVO.Interview();
                    interview.setLabelName(item.getLabelName());
                    interview.setKeyWord(String.format("%s-%s", item.getCategoryName(), item.getLabelName()));
                    interview.setSubjectName(item.getSubjectName());
                    interview.setSubjectAnswer(item.getSubjectAnswer());
                    return interview;
                }).collect(Collectors.toList());
        if (interviewList.size() > 8) {
            Collections.shuffle(interviewList);
            interviewList = interviewList.subList(0, 8);
        }
        InterviewQuestionVO vo = new InterviewQuestionVO();
        vo.setQuestionList(interviewList);
        return vo;
    }

    @Override
    public InterviewResultVO submit(InterviewSubmitReq req) {
        List<InterviewSubmitReq.Submit> questionList = req.getQuestionList();
        double sum = questionList.stream().mapToDouble(InterviewSubmitReq.Submit::getUserScore).sum();
        double avg = sum / questionList.size();
        String avgTips = EvaluateUtils.avgEvaluate(avg);
        String tip = questionList.stream()
                .map(item -> {
                    String labelName = item.getLabelName();
                    String evaluate = EvaluateUtils.evaluate(item.getUserScore());
                    return String.format(evaluate, labelName);
                })
                .distinct()
                .collect(Collectors.joining(";"));
        return InterviewResultVO.builder()
                .tips(tip)
                .avgScore(avg)
                .avgTips(avgTips)
                .build();
    }
}
